#!/bin/bash
#%depends: block
#%provides: tuda_partition_disks
#%programs: /bin/lsblk /sbin/mkfs /sbin/mkfs.ext2 /sbin/mkfs.minix /sbin/mkfs.vfat /sbin/mkfs.bfs /sbin/mkfs.ext3 /sbin/mkfs.msdos /sbin/mkdosfs /sbin/mkfs.xfs /sbin/mkfs.cramfs /sbin/mkfs.ext4 /sbin/mkfs.reiserfs /bin/gawk /sbin/blockdev /bin/dd /bin/grep /usr/sbin/parted /bin/sed /bin/sync /usr/bin/tr /sbin/mkswap /bin/sort /bin/vim-normal /usr/bin/tee /bin/date
#%stage: partitions
#Author: Geert Geurts, geert.geurts@hrz.tu-darmstadt.de
(
. /lib/tuda-lib.sh

rm /tmp/sda*
[ "$debug" ]&&echo "Running tuda_partition_disks.sh..."
PATH="/lib/tuda/bin/:$PATH"
PARTITIONSINFO=$(getarg partitionsinfo)
FSTYPES=$(getarg fstypes)
ROOT=$(getarg root)
FULL="$(getarg full|sed 's/_/ /')"
PROVNODE="$(getarg provnode)"
INSTIF="$(getarg instif)"
IP="$(ip addr show dev $INSTIF|grep 'inet '|gawk '{print $2}' |gawk -F'/' '{print $1}')"

if [ -z "$PARTITIONSINFO" ]; then 
	PARTITIONSINFO="/dev/sdb1:linux-swap:2000:200,/dev/sdb2:ext3:3700:370:/"; 
fi
if [ -z "$FSTYPES" ]; then
    FSTYPES="ext2|ext3|ext4|vfat|linux-swap"
fi
REFORMAT=0 #we assume formating is not needed...
[ "$debug" ]&&echo "tuda_partition_disks: FSTYPES=$FSTYPES"
[ "$debug" ]&&echo "tuda_partition_disks: PARTITIONSINFO=$PARTITIONSINFO"
#Ensure non mounted rootfs or others...
for M in $(grep -E $FSTYPES /proc/mounts|gawk '{print $2}'); do
	umount $M||/bin/bash
done
#go trough the comma seperated list of partitionsinfo option to the kernelcmdline
#SETvariables are options set on the cmdline
#DISCvariables are discovered variables by this script
for PARTINFO in $(echo $PARTITIONSINFO| tr ',' ' '); do
	#First unravel some option which were set...
    SETPARTINFO=($(echo $PARTINFO|tr : ' '))
	[ "$debug" ]&&echo "tuda_partition_disks: ${SETPARTINFO[@]}"
    SETPARTITION=${SETPARTINFO[0]} 						#/dev/sda1
	[ "$debug" ]&&echo "tuda_partition_disks: SETPARTITION=$SETPARTITION"
    SETTYPE=${SETPARTINFO[1]}      						#linux-swap
    [ "$debug" ]&&echo "tuda_partition_disks: SETTYPE=$SETTYPE"
	SETSIZE="$((${SETPARTINFO[2]}*1000000))" 					#2000x1000=2000000000 
    [ "$debug" ]&&echo "tuda_partition_disks: SETSIZE=$SETSIZE"
	SETFAULT=$((${SETPARTINFO[3]}*1000000))     				#200x1000=200000000
	[ "$debug" ]&&echo "tuda_partition_disks: SETFAULT=$SETFAULT"
    SETDISK=$(echo $SETPARTITION|sed 's/[0-9]//g') 				#/dev/sda
	[ "$debug" ]&&echo "tuda_partition_disks: SETDISK=$SETDISK"
	SETMOUNTPOINT=${SETPARTINFO[4]}
	if [ -n "$SETMOUNTPOINT" ]; then							
		echo "$SETMOUNTPOINT:$SETPARTITION">>/tmp/partitions	#if mountpoint is set, record it for later mounting in tuda_sync
	fi
	#Then discover the same info for the SETPARTITION
	#	DISCPARTINFO=($(lsblk -bn -o NAME,FSTYPE,SIZE $SETPARTITION 2>/dev/null|sed 's/swap/linux-swap/'))
	DISCPARTITION="/dev/$(lsblk -bn -o NAME $SETPARTITION 2>/dev/null)"
	DISCTYPE="$(lsblk -bn -o FSTYPE $SETPARTITION 2>/dev/null|sed 's/swap/linux-swap/')"
	DISCSIZE="$(lsblk -bn -o SIZE $SETPARTITION 2>/dev/null)"
	if [ -z "$DISCPARTITION" ] && [ -z "$DISCTYPE" ] && [ -z "$DISCSIZE" ]; then	#check to see if we discovered anything, if not set options to bogus values 
		DISCPARTITION=/dev/zzz
		DISCTYPE=none
		DISCSIZE=0
		DISCDISK=$SETDISK
	fi
	#Check the partition if the discovered type/size is what we want... If not append the disc to REFORMAT list
	if [ "$SETTYPE" == "extended" ] && [ "$DISCTYPE" == "" ]; then		#When extended partition continue with next partition
		continue
	else
		if [ $SETSIZE != 0 ] && [ "$SETTYPE" != "$DISCTYPE" ] || [ $SETSIZE != 0 ] && [ $(echo -e "$SETSIZE\n$DISCSIZE"|gawk 's{print ((s>$0)?s-$0:$0-s)}{s=$0}') -gt $SETFAULT ]; then
			[ "$debug" ]&&echo "tuda_partition_disks: SETSIZE=$SETSIZE"
			[ "$debug" ]&&echo "tuda_partition_disks: DISCSIZE=$DISCSIZE"
			[ "$debug" ]&&echo "tuda_partition_disks: SETFAULT=$SETFAULT"
			[ "$debug" ]&&echo "tuda_partition_disks: SETTYPE=$SETTYPE"
			[ "$debug" ]&&echo "tuda_partition_disks: DISCTYPE=$DISCTYPE"
			if [ "$SETTYPE" != "$DISCTYPE" ]; then
				if [ -z "$DISCTYPE" ]; then
					DISCTYPE="none"
				fi
				[ "$debug" ]&&echo "tuda_partition_disks: We expect a $SETTYPE partition on $SETPARTITION, instead we found a $DISCTYPE..."
				[ "$debug" ]&&echo "tuda_partition_disks: Going to reformat..."
			else
				[ "$debug" ]&&echo "tuda_partition_disks: Not good... to big of a difference between SET and DISCsize... This means we'll reformat $SETDISK"
				[ "$debug" ]&&echo DIFFERENCE=$(echo -e "$SETSIZE\n$DISCSIZE"|gawk 's{print ((s>$0)?s-$0:$0-s)}{s=$0}')
			fi
			if [ -z "$(echo $REFORMAT|grep $SETDISK)" ]; then
   	         	if [ "$REFORMAT" == "0" ]; then
   	             	REFORMAT=$SETDISK
   	        	 else
                	REFORMAT="$REFORMAT $SETDISK"
            	fi
        	fi
		fi
	fi
done
if [ $(date --date="$FULL" +%s) -ge $(date +%s) ] && [ -z "$(echo $REFORMAT|grep $ROOT)" ]; then  #reformat disk with root partition if full >= current date
        if [ "$REFORMAT" == "0" ]; then
               REFORMAT=$SETDISK
        else
               REFORMAT="$REFORMAT $SETDISK"
        fi
	
fi
if [ "$REFORMAT" != "0" ];then
    for DISK in $REFORMAT; do
		[ "$debug" ]&&echo "tuda_partition_disks: DISK=$DISK"
		[ "$debug" ]&&echo "tuda_partition_disks: REFORMAT=$REFORMAT"
		$DD if=/dev/zero of=$DISK bs=1024 count=1000 			#erase partitiontable
		parted $DISK mklabel msdos						#create a new empty partition table
		sync 							#flush the buffer on $DISK (following wait should be obsole if the sync is enough... NOT TESTED YET!!)
		R=1
		while [ $R -ne 0 ]; do
			[ "$debug" ]&&echo partition reread not ok
			blockdev --rereadpt $DISK 2>/dev/null					#re-read partiton table of $DISK
			R=$?
		done
		[ "$debug" ]&&echo partition reread seems ok....
		sync
		wait
		for PARTINFO in $(echo $PARTITIONSINFO|tr ',' ' '); do		#loop trough the partitions
			if [ -n "$(echo $PARTINFO|grep $DISK)" ]; then		#if its a partition on $DISK then...
				SETPARTINFO=($(echo $PARTINFO|tr : ' '))
				SETPARTITION=${SETPARTINFO[0]} 			#/dev/sda1
				SETTYPE=${SETPARTINFO[1]}      			#linux-swap
				SETSIZE="${SETPARTINFO[2]}" 			#2000000x1000=2000000000 
				SETFAULT="${SETPARTINFO[3]}"     		#200000x1000=200000000
				SETDISK=$(echo $SETPARTITION|sed 's/[0-9]//g')  #/dev/sda
				SETDISKNAME=$(echo $SETDISK|sed 's/^\/dev\///') #sda
				if [ -n "$(echo $SETTYPE|grep -E 'ext[234]')" ]; then			# if fstype is ext[234], then the partition type is ext2
					SETPARTTYPE="ext2"
				elif [ -n "$(echo $SETTYPE|grep 'fat')" ]; then #if fstype is vfat, then partition type is fat32
					SETPARTTYPE="fat32"			
				else						#else just takeover the SETTYPE setting
					SETPARTTYPE="$SETTYPE"
				fi
				[ "$debug" ]&&echo "tuda_partition_disks: $SETPARTITION:$SETPARTTYPE:$SETTYPE:$SETSIZE"
				echo "$SETPARTITION:$SETPARTTYPE:$SETTYPE:$SETSIZE">>/tmp/$SETDISKNAME.info #write partitioninfo ("/dev/sda1:ext2:ext3:2000000000")
			fi
		done
		START=0
		TYPE="primary"
		for PARTITION in $(sort /tmp/$SETDISKNAME.info); do             #Loop through partitions for this disk
		        PARTITIONAR=($(echo $PARTITION|tr ':' ' '))
		        PARTNR=$(echo ${PARTITIONAR[0]}|sed 's/^[a-zA-Z\/]*//') #1
		        BLOCKDEV=${PARTITIONAR[0]}                              #/dev/sda1
		        PARTTYPE=${PARTITIONAR[1]}                              #ext2
		        PARTFSTYPE=${PARTITIONAR[2]}                            #ext3
		        PARTSIZE="${PARTITIONAR[3]}"                              #2000000000
			if [ "$PARTTYPE" == "extended" ]; then
				PARTTYPE=""					#an extended partition doesnt contain any filesystem...
				TYPE="extended"					#set TYPE to extended
			fi 
			if [ "$PARTSIZE" == "-0" ]; then
				END="-0"				#If size is -0 then the remaining space is taken.
			else
				END=$(($START+$PARTSIZE))                               #0+2000000000=2000000000 for the first run. 
			fi
		        parted -s --align cylinder $DISK "mkpart $TYPE $PARTTYPE $START $END"   #define the partition
		        #sleep 4                                                #wait for changes to be active(SYNC MIGHT ALSO WORK!!)
		        sync
		        R=1
		        while [ $R -ne 0 ]; do
		                blockdev --rereadpt $DISK 2>/dev/null                           #re-read partitiontable
		                R=$?
		        done
		        sleep 4                                                 #wait for partition table to become active
		        sync
		        [ "$debug" ]&&echo "tuda_partition_disks: BLOCKDEV=$BLOCKDEV"
		        if [ "$PARTFSTYPE" == "linux-swap" ]; then              #if we\'re dealing with a swap partition...
		                mkswap $BLOCKDEV                                #mkswap $BLOCKDEV
		        elif [ "$PARTFSTYPE" != "extended" ]; then
		                /sbin/mkfs.$PARTFSTYPE $BLOCKDEV                        #otherwise there will be mkfs.$PARFSTYPE binary
		                sleep 4
		        fi
			if [ "$TYPE" != "extended" ]; then				#Dont change the START when we just created a extended partition(if PARTTYPE=extended then PARTYPE="")...
		        	START=$END
			else
				TYPE="logical"                                  #if the partition just created was a extended partition, the next is going to be a logical one
			fi 
		done
	/sbin/udevadm trigger							#update changes to udev
	rm /tmp/$SETDISKNAME.info						#cleanup
	done
else
	echo "tuda_partition_disks: Partitions seem fine..."
fi
) 2>&1 |tee /tmp/tuda_partition_disks.log||/bin/bash
